/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.huawei.spare.part.replace.views.prepare.spare;

import com.google.common.base.Strings;
import com.huawei.spare.part.replace.framework.SmartContentPresenter;
import com.huawei.spare.part.replace.framework.SmartDataBus;
import com.huawei.spare.part.replace.framework.SmartDatabase;
import com.huawei.spare.part.replace.models.Project;
import com.huawei.spare.part.replace.models.SerialNo;
import com.huawei.spare.part.replace.models.SwitchMatchedPackage;
import com.huawei.spare.part.replace.views.widgets.Alerts;
import com.huawei.spare.part.replace.views.widgets.FxUtils;
import com.huawei.spare.part.replace.views.widgets.toast.Toast;
import io.reactivex.Observable;
import io.reactivex.rxjavafx.observables.JavaFxObservable;
import io.reactivex.rxjavafx.schedulers.JavaFxScheduler;
import io.reactivex.schedulers.Schedulers;
import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import org.controlsfx.control.PopOver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URL;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;

/**
 * @author Woo
 */
public class SparePresenter extends SmartContentPresenter {

    private static final Logger log = LoggerFactory.getLogger(SparePresenter.class);

    @FXML TextField boardTypeTxtField;
    @FXML ComboBox<String> softwareVersionCombo;
    @FXML ComboBox<String> cpldVersionCombo;
    @FXML TextInputControl sn;
    @FXML Button loadBySnBtn;
    @FXML Hyperlink getSnLink;

    PopOver popOver;

    @Override
    public void initialize() {

        initialHowToGetSnPopOver();
        loadBySnBtn.disableProperty().bind(sn.textProperty().isEmpty());

        Platform.runLater(() -> {
            // addFormValidation();
            loading("common.message.loading", false);
            final SmartDatabase DB = SmartDatabase.get();
            JavaFxObservable.changesOf(boardTypeTxtField.textProperty()).subscribe((change) -> {
                log.info("Board Type Combo changed, reload other combo's data");
                final String series = change.getNewVal();
                if (!Strings.isNullOrEmpty(series)) {
                    final List<SwitchMatchedPackage> matches = DB.getSwitchMatchedPackage(series);
                    final List<String> softwareVersions = matches.stream()
                                                                 .map(SwitchMatchedPackage::getSoftwareVersion)
                                                                 .distinct()
                                                                 .sorted()
                                                                 .collect(Collectors.toList());
                    softwareVersionCombo.getItems().clear();
                    softwareVersionCombo.getItems().addAll(softwareVersions);
                    if (softwareVersionCombo.getSelectionModel().isEmpty()) {
                        softwareVersionCombo.getSelectionModel().select(0);
                    }

                    final List<String> cpldVersions = matches.stream().map(SwitchMatchedPackage::getCpldVersion)
                                                             .distinct()
                                                             .sorted()
                                                             .collect(Collectors.toList());
                    cpldVersionCombo.getItems().clear();
                    cpldVersionCombo.getItems().addAll(cpldVersions);
                    if (cpldVersionCombo.getSelectionModel().isEmpty()) {
                        cpldVersionCombo.getSelectionModel().select(0);
                    }
                }

                log.info("Board Type Combo changed, reload other combo data done");
            });

            Observable.defer((Callable<Observable<ObservableList<String>>>) () -> {
                return Observable.just(DB.getSwitchBordTypes());
            }).subscribeOn(Schedulers.io()).observeOn(JavaFxScheduler.platform()).subscribe((boardTypeList) -> {
                // setup auto complete
                FxUtils.autoCompleteComboBoxPlus(softwareVersionCombo, (typedText, item) -> item.toLowerCase().contains(typedText
                        .toLowerCase()));

                // prepare combo box data list
                boardTypeTxtField.textProperty().set(SmartDataBus.get().getProject().getDefective().getBoardType());
                cpldVersionCombo.setEditable(false);

                dismissLoading();
            }, (error) -> {
                log.error("failed", error);
                dismissLoading();
            });
        });

    }

    /**
     * initial how to get serial number popover
     */
    private void initialHowToGetSnPopOver() {
        final URL resource = getClass().getResource("/assets/images/how-to-get-sn.png");
        Image image = new Image(resource.toExternalForm().toString());
        ImageView howToImage = new ImageView(image);
        howToImage.setFitWidth(300D);
        howToImage.setFitHeight(200);
        howToImage.setPreserveRatio(true);
        popOver = new PopOver(howToImage);
        popOver.setArrowLocation(PopOver.ArrowLocation.TOP_LEFT);
        popOver.setArrowSize(8);
        popOver.setArrowIndent(28);
        getSnLink.setOnMouseClicked(mouseEvent -> {
            popOver.show(getSnLink, -8);
        });
    }

    @FXML
    public void loadBySn(ActionEvent actionEvent) {
        // 023LPV10HA000039
        String seriesNo = this.sn.getText();
        final SerialNo sn = SmartDatabase.get().getSn(seriesNo, boardTypeTxtField.textProperty().get(), true);
        if (sn != null) {
            if (sn.getBoardType().equals(boardTypeTxtField.textProperty())) {
                softwareVersionCombo.valueProperty().set(sn.getSolVersion());
                cpldVersionCombo.valueProperty().set(sn.getCpldVersion());
            } else {
                Toast.of(root(), String.format(getString("spare.sn.not.match"), sn.getBoardType())).show();
            }
        } else {
            Toast.of(root(), getString("spare.sn.not.found")).show();
        }
    }

    @Override
    public Observable<Boolean> onFinish() {
        final Project.Spare spare = new Project.Spare();
        spare.setBoardType(boardTypeTxtField.textProperty().get());
        spare.setSoftwareVersion(softwareVersionCombo.valueProperty().get());
        spare.setCpldVersion(cpldVersionCombo.valueProperty().get());

        final SwitchMatchedPackage matchedPackage = SmartDatabase.get()
                                                                 .findSwitchMatchedPackage(spare.getBoardType(), spare.getSoftwareVersion
                                                                         ());
        spare.setIsV5(matchedPackage.getIsV5());
        spare.setMatchedPackage(matchedPackage);

        final Project project = SmartDataBus.get().getProject();
        project.setSpare(spare);


        if (!matchedPackage.getCpldVersion().equalsIgnoreCase(spare.getCpldVersion())) {
            final String message = String.format(getString("spare.cpld.not.match"), spare.getCpldVersion(), matchedPackage
                    .getCpldVersion());
            final Optional<ButtonType> confirm = Alerts.confirm("common.title.op.confirm", message);
            return Observable.just(confirm.get().equals(ButtonType.OK));
        }


        return Observable.just(true);
    }

}
